#include <malloc.h>
#include <memory.h>
#include <stdbool.h>

typedef struct {
	unsigned account_nums;
	long long rest_money_a[];
} Bank;

Bank* bankCreate(long long balance_p[], int account_nums) {
	Bank* bank_p = malloc(sizeof(Bank) + sizeof(long long[account_nums]));
	bank_p->account_nums = account_nums;
	memcpy(bank_p->rest_money_a, balance_p,
	       sizeof(long long[account_nums]));
	return bank_p;
}

static unsigned _get_account_no(Bank* bank_p, int account) {
	unsigned account_nums = bank_p->account_nums;
	unsigned account_no = account - 1;
	if (account_no >= account_nums) {
		return -1;
	} else {
		return account_no;
	}
}

static bool _with_draw(Bank* bank_p, unsigned account_no, long long money) {
	long long* rest_p = &(bank_p->rest_money_a[account_no]);
	long long rest = *rest_p;
	if (rest < money) {
		return false;
	}
	*rest_p = rest - money;
	return true;
}

static void _deposit(Bank* bank_p, unsigned account_no, long long money) {
	bank_p->rest_money_a[account_no] += money;
}

bool bankTransfer(Bank* bank_p, int src_account, int dst_account,
		  long long money) {
	unsigned src_no = _get_account_no(bank_p, src_account);
	if (((int)src_no) < 0) {
		return false;
	}
	unsigned dst_no = _get_account_no(bank_p, dst_account);
	if (((int)dst_no) < 0) {
		return false;
	}
	bool with_draw_result = _with_draw(bank_p, src_no, money);
	if (!with_draw_result) {
		return false;
	}
	_deposit(bank_p, dst_no, money);
	return true;
}

bool bankDeposit(Bank* bank_p, int account, long long money) {
	unsigned account_no = _get_account_no(bank_p, account);
	if (((int)account_no) < 0) {
		return false;
	}
	_deposit(bank_p, account_no, money);
	return true;
}

bool bankWithdraw(Bank* bank_p, int account, long long money) {
	unsigned account_no = _get_account_no(bank_p, account);
	if (((int)account_no) < 0) {
		return false;
	}
	return _with_draw(bank_p, account_no, money);
}

void bankFree(Bank* bank_p) {
	free(bank_p);
}
